﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Xml.Linq;

using ClientDependency.Core;
using Google.YouTube;
using Google.GData.Client;
using Google.GData.YouTube;
using umbraco.controls;
using uTube.Core.Extensions;
using uTube.Core.Properties;

[assembly: WebResource("uTube.Core.DataTypes.YouTubeVideoPicker.YTVP_Styles.css", "text/css")]
[assembly: WebResource("uTube.Core.DataTypes.YouTubeVideoPicker.YTVP_Scripts.js", "application/javascript")]

namespace uTube.Core.DataTypes.YouTubeVideoPicker
{
	/// <summary>
	/// YouTube Video Picker control.
	/// </summary>
	public class YTVP_Control : PlaceHolder
	{
		/// <summary>
		/// Item template for the video DataList.
		/// </summary>
		private class VideoTemplate : ITemplate
		{
			/// <summary>
			/// When implemented by a class, defines the <see cref="T:System.Web.UI.Control"/> object that child controls and templates belong to. These child controls are in turn defined within an inline template.
			/// </summary>
			/// <param name="container">The <see cref="T:System.Web.UI.Control"/> object to contain the instances of controls from the inline template.</param>
			public void InstantiateIn(Control container)
			{
				var ph = new PlaceHolder() { ID = "ph" };
				container.Controls.Add(ph);
			}
		}

		/// <summary>
		/// Hidden input field to store the selected values.
		/// </summary>
		protected HtmlInputHidden HiddenValues;

		/// <summary>
		/// Gets or sets the options.
		/// </summary>
		/// <value>The options for the control.</value>
		public YTVP_Options Options { get; set; }

		/// <summary>
		/// Field value for the SelectedVideoIds property.
		/// </summary>
		private string _selectedVideoIds;

		/// <summary>
		/// Gets or sets the selected video ids.
		/// </summary>
		/// <value>The selected video ids.</value>
		public string SelectedVideoIds
		{
			get
			{
				if (this.HiddenValues != null)
				{
					this._selectedVideoIds = this.HiddenValues.Value;
				}

				return this._selectedVideoIds;
			}

			set
			{
				this._selectedVideoIds = value;
			}
		}

		/// <summary>
		/// Gets or sets the video data list.
		/// </summary>
		/// <value>The video data list.</value>
		protected DataList VideoDataList { get; set; }

		/// <summary>
		/// Handles the ItemDataBound event of the VideoDataList control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.Web.UI.WebControls.DataListItemEventArgs"/> instance containing the event data.</param>
		protected void VideoDataList_ItemDataBound(object sender, DataListItemEventArgs e)
		{
			if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
			{
				var ph = (PlaceHolder)e.Item.FindControl("ph");
				if (ph != null)
				{
					var video = (Video)e.Item.DataItem;
					var ltrl = new Literal();

					string cssClass = "video-item";
					if (!string.IsNullOrEmpty(this._selectedVideoIds) && this._selectedVideoIds.Contains(video.VideoId))
					{
						cssClass += " selected";
					}

					ltrl.Text = string.Format("<div class='{4}' rel='{0}' title='{1}'><img src='{3}' alt='{1}' width='120' /><br/>{2}</div>", video.VideoId, video.Title, umbraco.library.TruncateString(video.Title, 40, "..."), video.Thumbnails[0].Url, cssClass);

					ph.Controls.Add(ltrl);
				}
			}
		}

		/// <summary>
		/// Gets the video entries.
		/// </summary>
		/// <returns></returns>
		private IEnumerable<Video> GetVideoEntries()
		{
			var settings = new YouTubeRequestSettings(this.Options.ApplicationName, this.Options.DeveloperKey);
			var request = new YouTubeRequest(settings);
			
			var query = new YouTubeQuery(YouTubeQuery.DefaultVideoUri)
			{
				NumberToRetrieve = this.Options.MaxVideos,
				OrderBy = "viewCount",
				Query = this.Options.Query,
				SafeSearch = (YouTubeQuery.SafeSearchValues)this.Options.SafeSearch
			};

			Feed<Video> videoFeed = request.Get<Video>(query);

			return videoFeed.Entries;
		}

		/// <summary>
		/// Initialize the control, make sure children are created
		/// </summary>
		/// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

			this.EnsureChildControls();
		}

		/// <summary>
		/// Add the resources (sytles/scripts)
		/// </summary>
		/// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			// Adds the client dependencies.
			this.AddResourceToClientDependency("uTube.Core.DataTypes.YouTubeVideoPicker.YTVP_Styles.css", ClientDependencyType.Css);
			this.AddResourceToClientDependency("uTube.Core.DataTypes.YouTubeVideoPicker.YTVP_Scripts.js", ClientDependencyType.Javascript);

			if (this.Page.IsPostBack)
			{
				// populate the selected video ids
				this._selectedVideoIds = this.HiddenValues.Value;	
			}

			// check that the API key isn't empty
			if (!string.IsNullOrEmpty(this.Options.DeveloperKey))
			{
				// populate the video data-list.
				this.VideoDataList.ItemDataBound += new DataListItemEventHandler(VideoDataList_ItemDataBound);
				this.VideoDataList.DataSource = this.GetVideoEntries();
				this.VideoDataList.DataBind();
			}
		}

		/// <summary>
		/// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
		/// </summary>
		protected override void CreateChildControls()
		{
			base.CreateChildControls();

			this.EnsureChildControls();

			// construct the child controls
			this.HiddenValues = new HtmlInputHidden();
			this.VideoDataList = new DataList()
			{
				ItemTemplate = new VideoTemplate(),
				RepeatColumns = 3,
				RepeatDirection = RepeatDirection.Horizontal,
				RepeatLayout = RepeatLayout.Table,
				Width = 500
			};

			// add the child controls
			this.Controls.Add(this.HiddenValues);
			this.Controls.Add(this.VideoDataList);
		}

		/// <summary>
		/// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
		/// </summary>
		/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
		protected override void Render(HtmlTextWriter writer)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Class, "YTVP");
			writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
			writer.RenderBeginTag(HtmlTextWriterTag.Div);

			this.VideoDataList.RenderControl(writer);
			this.HiddenValues.RenderControl(writer);

			writer.RenderEndTag(); // .YTVP

			// add jquery window load event to create the ToggleBox
			var javascriptMethod = string.Format("jQuery('#{0}').YouTubeVideoPicker();", this.ClientID);
			var javascript = string.Concat("<script type='text/javascript'>jQuery(window).load(function(){ ", javascriptMethod, " });</script>");
			writer.WriteLine(javascript);
		}
	}
}
